package com.xcc.core.netty;


import com.xcc.core.config.PropertiesUtil;
import com.xcc.core.netty.coder.FixedLengthFrameDecoder;
import com.xcc.core.netty.coder.FixedLengthFrameEncoder;
import com.xcc.core.netty.server.Server3389handler;
import com.xcc.core.netty.server.ServerLengthHandler;
import com.xcc.core.netty.ssl.MyServerSslContextFactory;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.ssl.SslHandler;

public class NettyLengthServer {


    public static void main(String[] args) throws Exception {
        new Thread(()-> {
            try {
                startServer(PropertiesUtil.getIntValue("external.port"));
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }).start();
        new Thread(()-> {
            try {
                bind(PropertiesUtil.getIntValue("server.port"));
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }).start();
    }
    public static void bind(int port) throws Exception {
        
        EventLoopGroup bossGroup = new NioEventLoopGroup(); //bossGroup就是parentGroup，是负责处理TCP/IP连接的
        EventLoopGroup workerGroup = new NioEventLoopGroup(); //workerGroup就是childGroup,是负责处理Channel(通道)的I/O事件
        try {
            ServerBootstrap sb = new ServerBootstrap();
            sb.group(bossGroup, workerGroup)
            .channel(NioServerSocketChannel.class)
            //   .option(ChannelOption.SO_BACKLOG, 10) //初始化服务端可连接队列,指定了队列的大小128
              .childOption(ChannelOption.SO_KEEPALIVE, true) //保持长连接
            .childHandler(new ChannelInitializer<SocketChannel>() {  // 绑定客户端连接时候触发操作
                @Override
                protected void initChannel(SocketChannel sh) throws Exception {
                    sh.pipeline()
                    .addLast(new SslHandler(MyServerSslContextFactory.getsslServer()))   
                    .addLast(new FixedLengthFrameDecoder())   
                    .addLast(new FixedLengthFrameEncoder())   
                    .addLast(new ServerLengthHandler());
                }
            });
            //绑定监听端口，调用sync同步阻塞方法等待绑定操作完
            ChannelFuture future = sb.bind(port).sync();

            if (future.isSuccess()) {
                System.out.println("内部服务端启动成功"+port);
            } else {
                System.out.println("内部服务端启动失败");
            //    future.cause().printStackTrace();
            //    bossGroup.shutdownGracefully(); //关闭线程组
           //     workerGroup.shutdownGracefully();
            }
            future.channel().closeFuture().sync();
        }
        catch (Exception e) {
             e.printStackTrace();
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        } 
    }


    public static void startServer(int port) throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup(); //bossGroup就是parentGroup，是负责处理TCP/IP连接的
        EventLoopGroup workerGroup = new NioEventLoopGroup(); //workerGroup就是childGroup,是负责处理Channel(通道)的I/O事件
        ServerBootstrap sb = new ServerBootstrap();
        sb.group(bossGroup, workerGroup)
        .channel(NioServerSocketChannel.class)
        .childHandler(
            new ChannelInitializer<SocketChannel>() {

            @Override
            public void initChannel(SocketChannel ch) throws Exception {
                ch.pipeline().addLast(new  Server3389handler());
            }
        });
        //绑定监听端口，调用sync同步阻塞方法等待绑定操作完
        ChannelFuture future = sb.bind(port).sync();
        if (future.isSuccess()) {
            System.out.println("外部通信打开"+port);
        } else {
            System.out.println("外部通信打开");
       //     future.cause().printStackTrace();
      //      bossGroup.shutdownGracefully(); //关闭线程组
      //      workerGroup.shutdownGracefully();
        }
        future.channel().closeFuture().sync();
      
    }


}
